﻿using System.Collections.ObjectModel;
using System.Linq;
using System.Text.RegularExpressions;

namespace StyleAnalyzer
{
	/// <summary>
	/// Represents a stylesheet (CSS).
	/// </summary>
	public class StyleSheet
	{
		private static readonly Regex RuleDivider = new Regex(@"[^{]+{([^}].*?)}", RegexOptions.Compiled | RegexOptions.IgnoreCase);

		/// <summary>
		/// Initializes a new instance of the <see cref="StyleSheet"/> class.
		/// </summary>
		public StyleSheet()
		{
			Rules = new Collection<CssRule>();
		}

		/// <summary>
		/// Gets the list of CSS rules that is contained within this stylesheet.
		/// </summary>
		/// <value>The list of CSS rules.</value>
		public Collection<CssRule> Rules
		{
			get;
			private set;
		}

		/// <summary>
		/// Gets the stylesheet text in a minified version without comments and whitespace.
		/// </summary>
		public string MinifiedOutput
		{
			get;
			private set;
		}

		/// <summary>
		/// Gets whether or not the stylesheet was succesfully parsed.
		/// </summary>
		public bool IsSuccessfullyParsed
		{
			get
			{
				return Rules.FirstOrDefault(r => !r.IsSuccessfullyParsed) == null;
			}
		}

		/// <summary>
		/// Analyzes the specified CSS string by parsing and cleaning it.
		/// </summary>
		/// <param name="css">The CSS.</param>
		public void Analyze(string css)
		{
			css = RemoveWhiteSpaceFromStylesheets(css);
			foreach (Match match in RuleDivider.Matches(css))
			{
				Rules.Add(new CssRule(match.Value));
			}

			this.MinifiedOutput = css;
		}

		/// <summary>
		/// Strips the whitespace from any .css file.
		/// </summary>
		/// <param name="body">The body/contents of the CSS file.</param>
		/// <returns>The body of the CSS file stripped from whitespace and comments.</returns>
		private static string RemoveWhiteSpaceFromStylesheets(string body)
		{
			body = Regex.Replace(body, @"[a-zA-Z]+#", "#");
			body = Regex.Replace(body, @"[\n\r]+\s*", string.Empty);
			body = Regex.Replace(body, @"\s+", " ");
			body = Regex.Replace(body, @"\s?([:,;{}])\s?", "$1");
			body = body.Replace(";}", "}");
			body = Regex.Replace(body, @"([\s:]0)(px|pt|%|em)", "$1");

			// Remove comments from CSS
			body = Regex.Replace(body, @"/\*[\d\D]*?\*/", string.Empty);

			return body;
		}

	}
}
